<template>
  <div>
    <el-card class="card_search">
      <el-form class="role_search_form" :inline="true">
        <el-form-item label="角色名称">
          <el-input placeholder="请输入角色名称" v-model="keyword" />
        </el-form-item>
        <el-form-item>
          <el-button
            type="primary"
            :disabled="!keyword.trim()"
            @click="searchRole"
          >
            查询
          </el-button>
          <el-button type="info" @click="resetForm">重置</el-button>
        </el-form-item>
      </el-form>
    </el-card>
    <el-card>
      <el-button type="primary" icon="Plus" @click="addRole">
        添加角色
      </el-button>
      <el-table
        class="role_card_show"
        v-if="roleList.length > 0"
        border
        stripe
        :data="roleList"
      >
        <el-table-column label="#" align="center" type="index" width="100" />
        <el-table-column label="ID" align="center" prop="id" width="100" />
        <el-table-column label="角色名称" align="center" prop="roleName" />
        <el-table-column label="创建时间" align="center" prop="createTime" />
        <el-table-column label="更新时间" align="center" prop="updateTime" />
        <el-table-column label="操作" align="center" width="350">
          <template #default="{ row }">
            <el-button
              type="success"
              icon="User"
              @click="assignPermission(row)"
            >
              分配权限
            </el-button>
            <el-button type="warning" icon="Edit" @click="updateRole(row)">
              编辑
            </el-button>
            <el-popconfirm
              title="确定要删除该角色信息吗?"
              width="220"
              @confirm="deleteRole(row)"
            >
              <template #reference>
                <el-button type="danger" icon="Delete">删除</el-button>
              </template>
            </el-popconfirm>
          </template>
        </el-table-column>
      </el-table>
      <el-empty v-else />
      <el-pagination
        v-model:current-page="currentPage"
        v-model:page-size="pageSize"
        :page-sizes="[8, 16, 24, 32]"
        :size="'default'"
        :disabled="!(roleList.length > 0)"
        :background="true"
        layout="prev, pager, next, jumper, ->, total, sizes"
        :total="total"
        @size-change="handleSizeChange"
        @current-change="handleCurrentChange"
      />
    </el-card>
    <el-dialog
      v-model="dialogVisible"
      :title="RoleParams.id ? '修改角色' : '添加角色'"
      width="500"
      align-center
    >
      <el-form :model="RoleParams" :rules="RoleParamsRules" ref="form">
        <el-form-item label="角色名称" prop="roleName">
          <el-input
            placeholder="请输入角色名称"
            v-model="RoleParams.roleName"
          />
        </el-form-item>
      </el-form>
      <template #footer>
        <el-button type="info" @click="dialogVisible = false">取消</el-button>
        <el-button type="success" @click="addOrUpdateRole">确定</el-button>
      </template>
    </el-dialog>
    <el-drawer v-model="drawerVisible" direction="rtl">
      <template #header>
        <h4>分配角色权限</h4>
      </template>
      <template #default>
        <el-tree
          ref="tree"
          style="max-width: 600px"
          :data="rolePermissionArr"
          show-checkbox
          node-key="id"
          default-expand-all
          :default-checked-keys="selectArr"
          :props="defaultProps"
        />
      </template>
      <template #footer>
        <div style="flex: auto">
          <el-button type="info" @click="drawerVisible = false">取消</el-button>
          <el-button type="success" @click="confirmClick">确定</el-button>
        </div>
      </template>
    </el-drawer>
  </div>
</template>

<script setup lang="ts">
import { ref, onMounted, reactive, nextTick } from 'vue'
import { ElMessage } from 'element-plus'
// 引入接口
import {
  reqGetRoleList,
  reqDeleteRole,
  reqAddOrUpdateRole,
  reqGetPermission,
  reqAssignPermission,
} from '@/api/acl/role'
// 引入类型
import {
  PermissionList,
  Records,
  RoleData,
  RoleListResponseData,
  RolePermissionResponseData,
} from '@/api/acl/role/type'

// 定义当前页
let currentPage = ref<number>(1)
// 定义每页条数
let pageSize = ref<number>(8)
// 定义总记录数
let total = ref<number>(0)
// 定义搜索关键字
let keyword = ref<string>('')
// 定义角色列表数据
let roleList = ref<Records>([])
// 定义 dialog 组件是否显示的状态
let dialogVisible = ref<boolean>(false)
// 定义抽屉组件显示的状态
let drawerVisible = ref<boolean>(false)
// 获取 form 组件实例
let form = ref<any>()
// 收集角色数据
let RoleParams = reactive<RoleData>({
  roleName: '',
  id: '',
})
// 定义收集角色的权限数据
let rolePermissionArr = ref<PermissionList>([])
// 定义存储勾选的节点的 ID（四级的节点）\
let selectArr = ref<number[]>([])
// 获取 tree 组件的实例
let tree = ref<any>()
// 定义树型节点是否展示字段和子节点
const defaultProps = {
  children: 'children',
  label: 'name',
}

// 页面加载时获取角色列表数据
onMounted(() => {
  getRoleList()
})

// 获取角色列表数据
const getRoleList = async (page = 1) => {
  currentPage.value = page
  let result: RoleListResponseData = await reqGetRoleList(
    currentPage.value,
    pageSize.value,
    keyword.value,
  )
  if (result.code === 200) {
    total.value = result.data.total
    roleList.value = result.data.records
  }
}
// 分配权限按钮的回调
const assignPermission = async (row: RoleData) => {
  drawerVisible.value = true
  // 收集当前要分配权限的角色数据信息
  RoleParams.id = row.id
  let result: RolePermissionResponseData = await reqGetPermission(row.id)
  if (result.code === 200) {
    rolePermissionArr.value = result.data
    selectArr.value = filterSelectArr(rolePermissionArr.value, [])
  }
}
// 抽屉确定按钮的回调
const confirmClick = async () => {
  // 角色 ID
  const roleId = RoleParams.id as number
  // 选中的权限节点的 Id
  let arr = tree.value.getCheckedKeys()
  // 半选中的权限节点的 Id
  let halfArr = tree.value.getHalfCheckedKeys()
  let permissionId = arr.concat(halfArr)
  // 发请求
  let result = await reqAssignPermission(roleId, permissionId)
  if (result.code === 200) {
    ElMessage.success('分配权限成功')
  } else {
    ElMessage.error('分配权限失败')
  }
  drawerVisible.value = false
  // 刷新页面
  window.location.reload()
}
// 筛选出勾选的权限的节点 -- 递归
const filterSelectArr = (allData: any, initArr: any) => {
  allData.forEach((item: any) => {
    if (item.select && item.level === 4) {
      initArr.push(item.id)
    }
    if (item.children && item.children.length > 0) {
      filterSelectArr(item.children, initArr)
    }
  })
  return initArr
}

// 删除角色
const deleteRole = async (role: RoleData) => {
  let result = await reqDeleteRole(role.id)
  if (result.code === 200) {
    ElMessage.success('删除角色成功')
  } else {
    ElMessage.error('删除角色失败')
  }
  await getRoleList(
    roleList.value.length > 0 ? currentPage.value : currentPage.value - 1,
  )
}
// 添加角色
const addRole = () => {
  nextTick(() => {
    if (form.value) {
      form.value.clearValidate()
    }
  })
  RoleParams.id = ''
  RoleParams.roleName = ''
  dialogVisible.value = true
}
// 修改角色
const updateRole = (row: RoleData) => {
  nextTick(() => {
    if (form.value) {
      form.value.clearValidate()
    }
  })
  RoleParams.id = row.id
  RoleParams.roleName = row.roleName
  dialogVisible.value = true
}
// 添加或修改角色
const addOrUpdateRole = async () => {
  await form.value.validate()
  let result = await reqAddOrUpdateRole(RoleParams)
  if (result.code === 200) {
    ElMessage.success(RoleParams.id ? '修改角色成功' : '添加角色成功')
  } else {
    ElMessage.error(RoleParams.id ? '修改角色失败' : '添加角色失败')
  }
  dialogVisible.value = false
  await getRoleList(RoleParams.id ? currentPage.value : 1)
}
// 定义表单校验
const roleNameValidator = (rule: any, value: any, callback: any) => {
  if (value.trim() === '' || value.trim().length < 2) {
    callback(new Error('角色名称不能少于两个字符'))
  } else {
    callback()
  }
}
const RoleParamsRules = {
  roleName: [{ required: true, trigger: 'blur', validator: roleNameValidator }],
}
// 按条件搜索角色
const searchRole = () => {
  getRoleList()
  keyword.value = ''
}
// 重置表单
const resetForm = () => {
  keyword.value = ''
  getRoleList()
}
// 分页变化的回调
const handleSizeChange = (val: number) => {
  pageSize.value = val
  getRoleList()
}
// 当前页变化的回调
const handleCurrentChange = (val: number) => {
  getRoleList(val)
}
</script>

<style scoped>
.card_search {
  margin-bottom: 10px;
}
.role_search_form {
  margin-top: 10px;
  display: flex;
  justify-content: space-between;
  align-items: center;
}
.role_card_show {
  margin: 10px 0;
}
</style>
